
/*
 * (C)opyright 2010, Alessandro Agosto. All rights reserved.
 * This file is part of the "pycoev" project.
 * To get more informations about the license read the LICENSE file.
 *
 * pycoev.Loop type. Includes the new, clear, traverse and dealloc methods too.
 * Other methods (type methods) can be found in "pyc_loop_methods.c"
 */


#include "pyc_pyapis.h"
#include "pyc_event.h"
#include "pyc_loop.h"
#include "pyc_loop_methods.h"


static PyObject *PycLoop_New(PyTypeObject *, PyObject *, PyObject *);
static void PycLoop_Dealloc(Loop *);
static int PycLoop_Clear(Loop *);
static int PycLoop_Traverse(Loop *, visitproc visit, void *);


PyDoc_STRVAR(PycLoop_Doc, "Loop(max_timeout) -> new reference"             CRLF
                          "Main object type, this object can be instanced "
                          "only if the event-library has been initialized" CRLF
                          "Otherwise the __init__ method will raise an "
                          "exception."                                     CRLF
                          "This is the most useful object that creates "
                          "a new event loop and allows to use all methods "
                          "to handle it."                                  CRLF
                          "Follows a list of methods:");
                          /*TODO: continue here*/


Pyc_Methods PycLoop_Methods[] = {
    { "add", (PyCFunction)PycLoop_Add, METH_KEYWORDS, PycLoop_Add_Doc },
    { "delete", (PyCFunction)PycLoop_Delete, METH_VARARGS, PycLoop_Delete_Doc },
    { "loop_once", (PyCFunction)PycLoop_LoopOnce, METH_VARARGS,
      PycLoop_LoopOnce_Doc },
    { "set_timeout", (PyCFunction)PycLoop_SetTimeout, METH_VARARGS,
      PycLoop_SetTimeout_Doc },
    { "loop", (PyCFunction)PycLoop_Loop, METH_VARARGS, PycLoop_Loop_Doc },
    { NULL, NULL, 0, NULL }
};


PyTypeObject LoopType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    "pycoev.Loop",                            /*tp_name*/
    sizeof(Loop),                             /*tp_basicsize*/
    0,                                        /*tp_itemsize*/
    (destructor)PycLoop_Dealloc,              /*tp_dealloc*/
    0,                                        /*tp_print*/
    0,                                        /*tp_getattr*/
    0,                                        /*tp_setattr*/
    0,                                        /*tp_compare*/
    0,                                        /*tp_repr*/
    0,                                        /*tp_as_number*/
    0,                                        /*tp_as_sequence*/
    0,                                        /*tp_as_mapping*/
    0,                                        /*tp_hash */
    0,                                        /*tp_call*/
    0,                                        /*tp_str*/
    0,                                        /*tp_getattro*/
    0,                                        /*tp_setattro*/
    0,                                        /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT  | 
    Py_TPFLAGS_BASETYPE |
    Py_TPFLAGS_HAVE_GC,                       /*tp_flags*/
    PycLoop_Doc,                              /*tp_doc*/
    (traverseproc)PycLoop_Traverse,           /*tp_traverse*/
    (inquiry)PycLoop_Clear,                   /*tp_clear*/
    0,                                        /*tp_richcompare*/
    0,                                        /*tp_weaklistoffset*/
    0,                                        /*tp_iter*/
    0,                                        /*tp_iternext*/
    PycLoop_Methods,                          /*tp_methods*/
    0,                                        /*tp_members*/
    0,                                        /*tp_getsets*/
    0,                                        /*tp_base*/
    0,                                        /*tp_dict*/
    0,                                        /*tp_descr_get*/
    0,                                        /*tp_descr_set*/
    0,                                        /*tp_dictoffset*/
    0,                                        /*tp_init*/
    0,                                        /*tp_alloc*/
    PycLoop_New,                              /*tp_new*/
};


/*
 * tp_new
 * Creates a new Loop.
 */
static PyObject *
PycLoop_New(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
    int max_timeout, res;
    Loop *self; /*the new loop reference*/

    if (!PICOEV_IS_INITED) {
        Pyc_Fatal(Pyc_Error, "the event library must be initialized.");
    }

    res = PyArg_ParseTuple(args, "i:__init__", &max_timeout);
    if (!res) {
        Pyc_Fatal(NULL, NULL);
    }
    
    self = (Loop *)type->tp_alloc(type, 0);
    if (!self) {
        Pyc_Fatal(NULL, NULL);
    }
    
    self->loop = picoev_create_loop(max_timeout);
    if(NULL == &self->loop) {
        Pyc_Fatal(Pyc_Error, "failed creating a new loop");
    }

    return (PyObject *)self;
}


static int
PycLoop_Clear(Loop *self)
{
    Py_CLEAR(self->cb_arg);
    Py_CLEAR(self->callback);
    return 0;
}


/*
 * tp_dealloc
 * Destroys the "self" Loop.
 */
static void
PycLoop_Dealloc(Loop *self)
{
    if (self->loop) {
        picoev_destroy_loop(self->loop);
    }
}


/*
 * tp_traverse
 */
static int
PycLoop_Traverse(Loop *self, visitproc visit, void *arg)
{
    Py_VISIT(self->cb_arg);
    Py_VISIT(self->callback);
    return 0;
}

